package com.papercut.gui;

import java.util.List;
import java.util.UUID;

import org.androidpn.client.Constants;

import com.papercut.R;
import com.papercut.purchase.PurchaseEntity;
import com.papercut.purchase.PurchaseItem;
import com.papercut.purchase.PurchaseListAdapter;
import com.papercut.service.RestService;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import android.widget.Toast;

public class SwipeCheck extends Activity {
	
	private Handler handler;
	
	RestService mBoundService;
	// nodes, integer values of their resources
	int empty_node = R.drawable.empty_node;
	int[] nodes = new int[9];

	// view objects that get used multiple times
	TableRow[] rows = new TableRow[3];
	ImageView[] images = new ImageView[9];
	private TextView status_info;
	private ImageView action_button;

	// stack tracking variables
	private int[] stack = new int[9];
	private int[] saved_stack = new int[9];
	private int stack_current = 0;
	private boolean in_stack = false;
	private String[] saved_stack_key = { "one", "two", "three", "four", "five",
			"six", "seven", "eight", "nine" };

	// state tracking variables
	private boolean first_time;
	private boolean verify;
	private boolean change;
	
	private Context context;
	private String phone_number_string;
	private int round;
	
	private Intent intenta;
	
	private ProgressDialog progress = null;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		intenta = this.getIntent();
		
		progress = new ProgressDialog(this);
		handler = new Handler();
		
		context = this;
		final Intent intent = new Intent(SwipeCheck.this,
				com.papercut.service.RestService.class);
		bindService(intent, new ServiceConnection() {

			public void onServiceConnected(
					ComponentName name, IBinder service) {
				Log.d("ASDFASDF", "Came into onServiceConnected");
				mBoundService = ((RestService.LocalBinder) service)
						.getService();
				if (mBoundService == null) {
					Log.d("ASDFASDFASDF", "mboundservice is null");
				}
				Log.d("ASDFASDF", "Came out of onServiceConnected");

			}

			public void onServiceDisconnected(
					ComponentName name) {
				Log.i("Activity",
						"on disconnect" + name.toString());

			}

		}, Context.BIND_AUTO_CREATE);
		
		if (mBoundService == null) {
			Log.d("ASDFASDF", "NULL");
		}
		
		final SharedPreferences prefs = getSharedPreferences("storage", 0);
		boolean user_configured = prefs.getBoolean("userconfigured", false);
		boolean setup_mode = prefs.getBoolean("setupmode", false);

		if (!user_configured) {
			first_time = true;
			verify = false;
			change = false;
		} else if (setup_mode) {
			Editor editor = prefs.edit();
			editor.putBoolean("setupmode", false);
			editor.commit();
			first_time = false;
			verify = false;
			change = true;
		} else {
			first_time = false;
			verify = true;
			change = false;
		}

		round = 0;

		LinearLayout swipe_check_view = new LinearLayout(this);
		swipe_check_view.setOrientation(LinearLayout.VERTICAL);
		swipe_check_view
				.setBackgroundResource(R.drawable.amazon_background_swipecheck);

		TelephonyManager telephone_manager = (TelephonyManager) this
				.getSystemService(Context.TELEPHONY_SERVICE);
		phone_number_string = telephone_manager.getLine1Number();
		if (phone_number_string == null) {
			phone_number_string = "12223334444";
		}
		Log.d("Swipe", "Phone Number is " + phone_number_string);

		TextView phone_number_view = new TextView(this);   
		LinearLayout.LayoutParams phone_number_layout = new LinearLayout.LayoutParams(
				LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);

		phone_number_layout.setMargins(0, 20, 0, 0);
		phone_number_view.setText("Phone Number: " + phone_number_string);
		phone_number_view.setTextSize(16);
		phone_number_view.setTextColor(Color.rgb(231, 122, 0));
		phone_number_view.setGravity(Gravity.CENTER_HORIZONTAL);
		phone_number_view.setVisibility(TextView.VISIBLE);
		swipe_check_view.addView(phone_number_view, phone_number_layout);

		status_info = new TextView(this);
		LinearLayout.LayoutParams status_info_layout = new LinearLayout.LayoutParams(
				LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);

		status_info_layout.setMargins(0, 20, 0, 0);
		status_info.setTextSize(16);
		status_info.setTextColor(Color.GREEN);
		status_info.setText("Successful");
		status_info.setGravity(Gravity.CENTER_HORIZONTAL);

		if (first_time) {
			status_info.setTextColor(Color.RED);
			status_info.setText("Need to create Swipe Key");

		} else if (change) {
			status_info.setTextColor(Color.BLACK);
			status_info.setText("Verify current Swipe Key");

		} else {
			status_info.setTextColor(Color.BLACK);
			status_info.setText("Verify Swipe Key");
		}

		swipe_check_view.addView(status_info, status_info_layout);

		// Setting up all the nodes and stuff

		nodes[0] = R.drawable.nine_node;
		nodes[1] = R.drawable.eight_node;
		nodes[2] = R.drawable.seven_node;
		nodes[3] = R.drawable.six_node;
		nodes[4] = R.drawable.five_node;
		nodes[5] = R.drawable.four_node;
		nodes[6] = R.drawable.three_node;
		nodes[7] = R.drawable.two_node;
		nodes[8] = R.drawable.one_node;

		TableLayout table = new TableLayout(this);

		for (int x = 0; x < 3; x++) {
			rows[x] = new TableRow(this);
		}

		for (int x = 0; x < 9; x++) {
			images[x] = new ImageView(this);
			images[x].setImageResource(R.drawable.empty_node);
			images[x].setOnTouchListener(new OnTouchListener() {

				@Override
				public boolean onTouch(View arg0, MotionEvent event) {
					if (event.getAction() == MotionEvent.ACTION_DOWN) {
						for (int x = 0; x < stack.length; x++) {
							stack[x] = 9;
							images[x].setImageResource(empty_node);
						}
						stack_current = 0;
						in_stack = false;
					}
					for (int x = 0; x < rows.length; x++) {
						for (int y = 0; y < rows.length; y++) {
							if (event.getRawX() > 40 + 150 * x
									&& event.getRawX() < 140 + 150 * x
									&& event.getRawY() > 150 + 150 * y
									&& event.getRawY() < 250 + 150 * y) {
								in_stack = false;
								for (int a = 0; a < stack.length; a++) {
									if (stack[a] == x + 3 * y) {
										in_stack = true;
									}
								}
								if (!in_stack) {
									stack[stack_current] = x + 3 * y;
									images[x + 3 * y]
											.setImageResource(nodes[stack_current]);
									stack_current++;
								}
							}
						}
					}
					if (event.getAction() == MotionEvent.ACTION_UP) {
						int countNumMissing = 0;
						for (int x = 0; x < stack.length; x++) {
							if (stack[x] == 9) {
								countNumMissing++;
							}
						}
						if (countNumMissing > 4) {
							status_info.setText("Use at least 5 nodes");
							for (int x = 0; x < stack.length; x++) {
								images[x].setImageResource(empty_node);
								stack[x] = 9;
							}
						}
					}
					return true;
				}

			});
		}

		// Set up padding and location of images
		images[0].setPadding(40, 40, 25, 25);
		images[1].setPadding(25, 40, 25, 25);
		images[2].setPadding(25, 40, 40, 25);

		images[3].setPadding(40, 25, 25, 25);
		images[4].setPadding(25, 25, 25, 25);
		images[5].setPadding(25, 25, 40, 25);

		images[6].setPadding(40, 25, 25, 40);
		images[7].setPadding(25, 25, 25, 40);
		images[8].setPadding(25, 25, 40, 40);

		for (int x = 0; x < rows.length; x++) {
			for (int y = 0; y < rows.length; y++) {
				rows[y].addView(images[x + 3 * y]);
			}
		}

		for (int x = 0; x < rows.length; x++) {
			table.addView(rows[x]);
		}

		swipe_check_view.addView(table);

		action_button = new ImageView(this);
		LinearLayout.LayoutParams action_button_layout = new LinearLayout.LayoutParams(
				LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
		action_button_layout.setMargins(125, 20, 125, 0);
		if (first_time) {
			action_button.setImageResource(R.drawable.save_button);
		} else if (change) {
			action_button.setImageResource(R.drawable.verify_button);
		} else {
			action_button.setImageResource(R.drawable.verify_button);
		}
		action_button.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View arg0) {
				if (first_time) {
					if (round == 0) {
						SharedPreferences prefs = getSharedPreferences(
								"storage", 0);
						Editor editor = prefs.edit();
						for (int x = 0; x < saved_stack.length; x++) {
							editor.putInt(saved_stack_key[x], stack[x]);
							images[x].setImageResource(empty_node);
						}
						editor.commit();

						status_info.setText("Enter sequence again to confirm");
						action_button
								.setImageResource(R.drawable.verify_button);
						round = 1;
					} else if (round == 1) {
						boolean failed = false;
						int[] shared_stack = new int[9];
						final SharedPreferences prefs = getSharedPreferences(
								"storage", 0);
						for (int x = 0; x < saved_stack.length; x++) {
							shared_stack[x] = prefs.getInt(saved_stack_key[x],
									9);
						}
						for (int x = 0; x < saved_stack.length; x++) {
							if (shared_stack[x] != stack[x]) {
								failed = true;
							}
							images[x].setImageResource(empty_node);
						}
						if (failed) {
							round = 0;
							status_info
									.setText("Confirmation Failed. Try again.");
							action_button
									.setImageResource(R.drawable.save_button);

						} else {
							String swipeCode = "";
							for (int i = 0; i < stack.length; i++) {
								swipeCode += "" + stack[i];
							}
							final String swipeFinal = swipeCode;
							
							//final String deviceID = ((TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE)).getDeviceId();
							
							
							SharedPreferences sharedPrefs = getSharedPreferences(Constants.SHARED_PREFERENCE_NAME,
					                Context.MODE_PRIVATE);
							
							final String deviceID = sharedPrefs.getString(Constants.XMPP_USERNAME, "");
							if(deviceID.equals("")){
								Editor editor = sharedPrefs.edit();
                                editor.putString(Constants.XMPP_USERNAME,
                                		newRandomUUID());
                                editor.putString(Constants.XMPP_PASSWORD,
                                		newRandomUUID());
                                editor.commit();
							}
							
							ICallback callback = new ICallback() {
								
								@Override
								public void success(Object data) {
									Editor editor = prefs.edit();
									editor.putBoolean("userconfigured", true);
									editor.commit();
									handler.post(new Runnable () {
										public void run()
										{
											progress.dismiss();
							    			int duration = Toast.LENGTH_SHORT;
											CharSequence text = "Successful";

							    			Toast toast = Toast.makeText(SwipeCheck.this, text, duration);
							    			toast.show();

										}
									});

									Intent dash_board_intent = new Intent(
											SwipeCheck.this, DashBoard.class);
									startActivityForResult(dash_board_intent, 40);
									Log.d("QWERQWER", "success");
									
								}
								
								@Override
								public void failure(String error) {
									Log.d("ASDFADSF", "Failing");
								}
							};
							Log.d("About to start registert hread", "ASDFASDFASFD");
							Thread registerThread = new Thread(new RegisterThread(callback, phone_number_string, deviceID, swipeFinal));
							progress.setMessage("Loading...");
							progress.show();
							registerThread.start();
						}
					}
				} else if (change) {
					if (round == 0) {
						//Put all the code to obtain the string stored in server back
						
						String swipeCode = "";
						for (int i = 0; i < stack.length; i++) {
							swipeCode += "" + stack[i];
						}
						final String swipeFinal = swipeCode;
												
						ICallback callback = new ICallback() {

							@Override
							public void success(Object data) {
								round = 1;
								Log.d("callback change", "success");
								handler.post(new Runnable () {
									public void run()
									{
										progress.dismiss();
										status_info.setText("Create new Swipe Key");
										action_button.setImageResource(R.drawable.save_button);		
										
										for (int x = 0; x < images.length; x++) {
											images[x].setImageResource(empty_node);
										}

									}
								});
							}

							@Override
							public void failure(String error) {
								round = 0;
								Log.d("callback change", "failure");
								handler.post(new Runnable () {
									public void run()
									{
										progress.dismiss();
										status_info.setText("Verification Failed. Try again.");
										action_button.setImageResource(R.drawable.verify_button);	
										for (int x = 0; x < images.length; x++) {
											images[x].setImageResource(empty_node);
										}

									}
								});
							}
						};
						Thread authenticateThread = new Thread(new AuthenticateThread(callback, swipeFinal));
						progress.setMessage("Loading...");
						progress.show();
						authenticateThread.start();
						
					} else if (round == 1) {
						SharedPreferences prefs = getSharedPreferences(
								"storage", 0);
						Editor editor = prefs.edit();
						for (int x = 0; x < saved_stack.length; x++) {
							editor.putInt(saved_stack_key[x], stack[x]);
							images[x].setImageResource(empty_node);
						}
						editor.commit();
						status_info.setText("Enter sequence again to confirm");
						action_button
								.setImageResource(R.drawable.verify_button);
						round = 2;
					} else if (round == 2) {
						Log.d("coming into 2nd part", "at least");
						boolean failed = false;
						int[] shared_stack = new int[9];
						final SharedPreferences prefs = getSharedPreferences(
								"storage", 0);
						for (int x = 0; x < saved_stack.length; x++) {
							shared_stack[x] = prefs.getInt(saved_stack_key[x],
									9);
						}
						for (int x = 0; x < saved_stack.length; x++) {
							if (shared_stack[x] != stack[x]) {
								failed = true;
							}
							images[x].setImageResource(empty_node);
						}
						if (failed) {
							round = 1;
							Log.d("Something", "Went wrong");
							status_info.setText("Verification Failed. Try again.");

						} else {
							Log.d("coming into 3nd part", "at least");

							String swipeCode = "";
							for (int i = 0; i < stack.length; i++) {
								swipeCode += "" + stack[i];
							}
							final String swipeFinal = swipeCode;
							
							//final String deviceID = ((TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE)).getDeviceId();
							
							SharedPreferences sharedPrefs = getSharedPreferences(Constants.SHARED_PREFERENCE_NAME,
					                Context.MODE_PRIVATE);
							
							final String deviceID = sharedPrefs.getString(Constants.XMPP_USERNAME, "");
							if(deviceID.equals("")){
								Editor editor = sharedPrefs.edit();
                                editor.putString(Constants.XMPP_USERNAME,
                                		newRandomUUID());
                                editor.putString(Constants.XMPP_PASSWORD,
                                		newRandomUUID());
                                editor.commit();
							}
							
							///TODO: do this on another thread
							
							ICallback callback = new ICallback() {
								
								@Override
								public void success(Object data) {
									handler.post(new Runnable () {
										public void run()
										{
											progress.dismiss();
							    			int duration = Toast.LENGTH_SHORT;
											CharSequence text = "Successful";

							    			Toast toast = Toast.makeText(SwipeCheck.this, text, duration);
							    			toast.show();

										}
									});
									finish();
								}
								
								@Override
								public void failure(String error) {
								}
							};
							Thread registerThread = new Thread(new RegisterThread(callback, phone_number_string, deviceID, swipeFinal));
							progress.setMessage("Loading...");
							progress.show();							
							registerThread.start();
						}
					}

				} else {
					boolean failed = false;
					int[] shared_stack = new int[9];
					SharedPreferences prefs = getSharedPreferences("storage", 0);
					for (int x = 0; x < saved_stack.length; x++) {
						shared_stack[x] = prefs.getInt(saved_stack_key[x], 9);
					}
					for (int x = 0; x < saved_stack.length; x++) {
						if (shared_stack[x] != stack[x]) {
							failed = true;
						}
						images[x].setImageResource(empty_node);
					}
					if (failed) {
						status_info.setText("Verification Failed. Try again.");
					} else {
						//Put all the code to obtain the string stored in server back
						
						String swipeCode = "";
						for (int i = 0; i < stack.length; i++) {
							swipeCode += "" + stack[i];
						}
						final String swipeFinal = swipeCode;
												
						
						ICallback callback = new ICallback() {

							@Override
							public void success(Object data) {
								round = 1;
								Log.d("callback change", "success");
								handler.post(new Runnable () {
									public void run()
									{
										progress.dismiss();
						    			int duration = Toast.LENGTH_SHORT;
										CharSequence text = "Successful";

						    			Toast toast = Toast.makeText(SwipeCheck.this, text, duration);
						    			toast.show();
										SharedPreferences prefs = getSharedPreferences(
												"storage", 0);
										boolean a = prefs.getBoolean("VERIFYTHING", false);
										if (a) {

											SharedPreferences prefs2 = getSharedPreferences("storage", 0);
											Editor editor = prefs2.edit();
											editor.putBoolean("YAY", true);
											editor.commit();
										}
										finish();

										//status_info.setText("Create new Swipe Key");
										//action_button.setImageResource(R.drawable.save_button);		
										//for (int x = 0; x < images.length; x++) {
										//	images[x].setImageResource(empty_node);
										//}

									}
								});
							}

							@Override
							public void failure(String error) {
								round = 0;
								Log.d("callback change", "failure");
								handler.post(new Runnable () {
									public void run()
									{
										progress.dismiss();
										status_info.setText("Verification Failed. Try again.");
										action_button.setImageResource(R.drawable.verify_button);	
										for (int x = 0; x < images.length; x++) {
											images[x].setImageResource(empty_node);
										}
										
										
										SharedPreferences prefs = getSharedPreferences(
												"storage", 0);
										boolean a = prefs.getBoolean("VERIFYTHING", false);
										if (a) {
											SharedPreferences prefs2 = getSharedPreferences("storage", 0);
											Editor editor = prefs2.edit();
											editor.putBoolean("YAY", false);
										} else {
											
										}

									}
								});
							}
						};
						Thread authenticateThread = new Thread(new AuthenticateThread(callback, swipeFinal));
						progress.setMessage("Loading...");
						progress.show();
						authenticateThread.start();
					}
				}
			}

		});
		swipe_check_view.addView(action_button, action_button_layout);

		setContentView(swipe_check_view);

	}

	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		finish();
	}
	
	private class RegisterThread implements Runnable{
		private final ICallback callback;
		private final String phoneNumber;
		private final String androidId;
		private final String swipe;
		public RegisterThread(ICallback callback, String phoneNumber, String androidId, String swipe){
			this.callback = callback;
			this.phoneNumber = phoneNumber;
			this.androidId =androidId;
			this.swipe = swipe;
		}
		
		@Override
		public void run() {
			boolean success = mBoundService.register(phoneNumber, androidId, swipe);
			if(success){
				Log.d("asdfasdf", "Callback success");
				this.callback.success(null);
			}
			else{
				this.callback.failure(null);
			}
		}
		
	}
	
	private class AuthenticateThread implements Runnable{
		private final ICallback callback;
		private final String swipe;
		
		public AuthenticateThread(ICallback callback, String swipe){
			this.callback = callback;
			this.swipe = swipe;
		}
		
		@Override
		public void run() {
			boolean success = mBoundService.authenticateSwipe(swipe);
			if(success){
				Log.d("asdfasdf", "Callback success");
				this.callback.success(success);
			}
			else{
				this.callback.failure(null);
			}
		}
		
	}
    private String newRandomUUID() {
        String uuidRaw = UUID.randomUUID().toString();
        return uuidRaw.replaceAll("-", "");
    }
}
